package cn.tianya.irock.util;

public class IPAddress {
	private long address;
	
	public static final IPAddress Any = new IPAddress(0);
	public static final IPAddress Broadcast = IPAddress.parse("255.255.255.255");
	public static final IPAddress Loopback = IPAddress.parse("127.0.0.1");
	public static final IPAddress None = IPAddress.parse("255.255.255.255");
	
	public IPAddress(long addr) {
		address = addr;
	}
	
	public long getAddress() {
		return address;
	}

	public void setAddress(long address) {
		this.address = address;
	}


	public static IPAddress parse(String ip) {
		IPAddress ret;

		if (ip == null)
			throw new IllegalArgumentException ("Value cannot be null.");
			
		if( (ret = parseIPV4(ip)) == null)
			throw new IllegalArgumentException("An invalid IP address was specified.");

		return ret;
	}
	
	private static IPAddress parseIPV4 (String ip) {
		if (ip.length() == 0 || ip.equals(" "))
			return new IPAddress(0);
			
		int pos = ip.indexOf(' ');
		if (pos != -1) {
			ip = ip.substring(0, pos);
		}
		

		if (ip.length() == 0 || ip.charAt(ip.length() - 1) == '.')
			return null;

		String [] ips = ip.split("\\.");
		if (ips.length > 4)
			return null;
		
		// Make the number in network order
		try 
		{
			long a = 0;
			int val = 0;
			for (int i = 0; i < ips.length; i++) {
				String subnet = ips [i];
				if ((3 <= subnet.length() && subnet.length() <= 4) && 
					(subnet.charAt(0) == '0') && 
					(subnet.charAt(1) == 'x' || subnet.charAt(2) == 'X')) {
					if (subnet.length() == 3) {
						val = (byte) fromHex (subnet.charAt(2));
					} else { 
						val = (byte) ((fromHex (subnet.charAt(2)) << 4) | fromHex (subnet.charAt(3)));
					}
				} else if (subnet.length() == 0) {
					return null;
				} else { 
					val = Integer.parseInt(subnet);
					if (val > 255) {
						return null;
					}
				}
				
				if (ips.length < 4 && i == (ips.length - 1)) 
					i = 3;

				a |= (long) val << (i << 3);
			}

			return (new IPAddress (a));
		} catch (RuntimeException e) {
			return null;
		}
	}
	
	private static int fromHex (char digit) 	{
		if ('0' <= digit && digit <= '9') {
			return (int) (digit - '0');
		}
			
		if ('a' <= digit && digit <= 'f')
			return (int) (digit - 'a' + 10);

		if ('A' <= digit && digit <= 'F')
			return (int) (digit - 'A' + 10);
			
		throw new IllegalArgumentException("digit");
	}
	
	public String toString () {
		return  Long.toString(this.address & 0xff) + "." +
				Long.toString((this.address >> 8) & 0xff) + "." +
				Long.toString((this.address >> 16) & 0xff) + "." +
				Long.toString((this.address >> 24) & 0xff);
	}
}
